#include <stdio.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <stdatomic.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#include <signal.h>
#include <sys/socket.h>

#include "server_xml_concise.h"
#include "reply_generator.h"

#define PORT 8080
#define BUFFER_SIZE 2048
#define SHMSZ 1024

struct TSNConfig tsnconfig;

const char *infile = "netconf_mdfile/server_input.xml";
const char *outfile = "netconf_mdfile/server_output.xml";

struct Tunnel *tunnel;
int server_fd = -1, client_fd = -1;
int handle = 0;
struct sockaddr_in server_addr, client_addr;

void initializeTunnel(struct Tunnel *tunnel)
{
    // 使用memset初始化数组为0
    memset(tunnel->TC, 0, sizeof(tunnel->TC));
    memset(&tunnel->PI, 0, sizeof(tunnel->PI));

    // 初始化指针为NULL
    strcpy(tunnel->mes, "");
    strcpy(tunnel->m_id, "");
    strcpy(tunnel->op, "");

    // 初始化num和num相关信息
    tunnel->TC_num = 0;
    tunnel->error = 0;
    atomic_store_explicit(&tunnel->tag, 0, memory_order_release);
}

void signal_handler(int signum)
{
    if (signum == SIGINT)
    {
        // 关闭套接字
        close(server_fd);
        close(client_fd);

        printf("server_fd和client_fd套接字已关闭\n");
        // 清理并退出程序
        exit(signum);
    }
}

int main()
{
    int i = 0;
    socklen_t client_len = sizeof(client_addr);
    char buffer[BUFFER_SIZE];
    key_t key = ftok("netconf_mdfile/client_input.xml", 'a');
    if (key == -1)
    {
        perror("ftok");
        exit(EXIT_FAILURE);
    }

    int shmid = shmget(key, 10000, IPC_CREAT | 0666);
    // printf("size=%ld", sizeof(struct Tunnel));
    if (shmid == -1)
    {
        perror("shmget");
        exit(EXIT_FAILURE);
    }
    tunnel = (struct Tunnel *)shmat(shmid, NULL, 0);
    initializeTunnel(tunnel);

    // 创建套接字
    server_fd = socket(AF_INET, SOCK_STREAM, 0);
    printf("server_fd:%d\n", server_fd);
    if (server_fd < 0)
    {
        perror("Could not create socket");
        exit(1);
    }

    // 设置服务器地址
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);

    int yes = 1;  
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {  
        perror("setsockopt");  
        exit(1);  
    } 

    // 绑定套接字
    if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    {
        perror("Bind failed");
        exit(1);
    }

    // 监听连接
    if (listen(server_fd, 3) < 0)
    {
        perror("Listen failed");
        exit(1);
    }

    // while保证客户端断开连接后，服务器继续监听其他客户端连接
    while (1)
    {

        // 接受连接
        printf("Waiting for client...\n");
        client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_len);
        printf("client_fd:%d\n", client_fd);
        if (client_fd < 0)
        {
            perror("Accept failed");
            exit(1);
        }
        printf("Client connected\n");

        // 接收并执行客户端命令
        char buffer[2048];
        int running = 1;

        while (running)
        {
            // 监听信号量
            signal(SIGINT, signal_handler);

            int bytes = read(client_fd, buffer, BUFFER_SIZE);
            // 解析xml文件
            printf("bytes=%d\n", bytes);
            if (bytes == 0)
            {
                running = 0;
                continue;
            }

            FILE *file = fopen(infile, "w");
            if (file == NULL)
            {
                perror("无法打开hello文件");
                return 0;
            }
            size_t bytes_read = fwrite(buffer, sizeof(char), bytes, file);
            memset(buffer, 0, 1024);
            fclose(file);
            while (atomic_load_explicit(&tunnel->tag, memory_order_acquire))
                ;
            parse_rpc(infile, tunnel);
            printf("已解析\n");
            // printf("Tunnel ID: %s\n", tunnel->mes);
            int k = 0;
            for (; k < tunnel->TC_num; k++)
            {
                printf("Tunnel ID: %s\n", tunnel->TC[k].entity);
                printf("Tunnel Content: %s\n", tunnel->TC[k].content);
            }

            atomic_store_explicit(&tunnel->tag, 1, memory_order_release);

            printf("早岁已知世事艰，仍许飞鸿荡云间\n");

            // write_TSNConfig(&tsnconfig, tunnel);
            while (atomic_load_explicit(&tunnel->tag, memory_order_acquire))
                ;
            rply_generator(outfile, tunnel);
            file = fopen(outfile, "r");
            printf("已经生成响应");
            if (file == NULL)
            {
                perror("无法打开XML响应文件");
                return 0;
            }
            bytes_read = fread(buffer, sizeof(char), BUFFER_SIZE, file);
            fclose(file);
            send(client_fd, buffer, strlen(buffer), 0);
        }
    }
    // 关闭套接字
    close(client_fd);
    close(server_fd);

    return 0;
}
